//***************************************************************************** // // The "setproxy" command allows the user to change their proxy behavior // //***************************************************************************** int Cmd_setproxy(int argc, char *argv[]) { char pcProxyPort[10]; // // Check the number of arguments. // if((argc == 2) && (ustrcmp("off",argv[1]) == 0 )) { g_bUseProxy = false; g_pcProxyAddress[0] = 0; g_ui16ProxyPort = 0; UARTprintf("Attempting to re-establish link with Exosite.\n\n"); g_bOnline = LocateValidCIK(); } else if(argc == 3) { // // Otherwise, copy the user-defined location into the global variable. // ustrncpy(g_pcProxyAddress, argv[1], 49); ustrncpy(pcProxyPort, argv[2], 9); // // Make sure that the global string remains terminated with a zero. // g_pcProxyAddress[49] = 0; pcProxyPort[9] = 0; g_ui16ProxyPort = ustrtoul(pcProxyPort, NULL, 0); g_bUseProxy = true; UARTprintf("New Proxy Address: %s\n", g_pcProxyAddress); UARTprintf("New Proxy Port: %d\n\n", g_ui16ProxyPort); UARTprintf("Attempting to re-establish link with Exosite.\n\n"); g_bOnline = LocateValidCIK(); } else { UARTprintf("\nProxy configuration help:\n"); UARTprintf(" The setproxy command changes the proxy behavior of" "this board.\n"); UARTprintf(" To disable the proxy, type:\n\n"); UARTprintf(" setproxy off\n\n"); UARTprintf(" To enable the proxy with a specific proxy name and " "port, type\n"); UARTprintf(" setproxy <proxyaddress> <portnumber>. For " "example:\n\n"); UARTprintf(" setproxy your.proxy.address 80\n\n"); } return 0; }
//***************************************************************************** // // The alert command allows the user to send an alert message to the saved // email address. // //***************************************************************************** int Cmd_alert(int argc, char *argv[]) { uint32_t ui32Index; // // Check the number of arguments. // if(argc < 2) { // // If there was no second term, prompt the user to enter one next time. // UARTprintf("Please specify the alert you want to send:\n"); for(ui32Index = 0; ui32Index < NUM_ALERTS; ui32Index++) { // // Print a list of the available alert messages. // UARTprintf("alert %d: %s\n", ui32Index, g_ppcAlertMessages[ui32Index]); } } else { ui32Index = ustrtoul(argv[1], NULL, 0); ustrncpy(g_pcAlert, g_ppcAlertMessages[ui32Index], 140); g_sAlert.eReadWriteType = READ_WRITE; UARTprintf("Alert message set. Sending to the server " "on the next sync operation."); } return 0; }
//***************************************************************************** // // The setemail command allows the user to set a contact email address to be // used for alert messages. // //***************************************************************************** int Cmd_setemail(int argc, char *argv[]) { // // Check the number of arguments. // if(argc < 2) { // // If there was no second term, prompt the user to enter one next time. // UARTprintf("Not enough arguments. Please enter an email address.\n"); UARTprintf("For example \"setemail [email protected]\""); } else { // // Otherwise, copy the user-defined location into the global variable. // ustrncpy(g_pcContactEmail, argv[1], 100); // // Make sure that the global string remains terminated with a zero. // g_pcContactEmail[99] = 0; // // Mark the location as READ_WRITE, so it will get uploaded to the // server on the next sync. // g_sContactEmail.eReadWriteType = READ_WRITE; UARTprintf("Email set to: %s\n\n", g_pcContactEmail); } return 0; }
/* This is an internal wrapper around the user thread function. Its * purpose is to handle all the necessary housekeeping stuff so that the * user function needs not to be aware of the threading calls. The user * function call has just "normal", non-threading semantics. * rgerhards, 2007-12-17 */ static void* thrdStarter(void *arg) { DEFiRet; thrdInfo_t *pThis = (thrdInfo_t*) arg; # if HAVE_PRCTL && defined PR_SET_NAME uchar thrdName[32] = "in:"; # endif assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); ustrncpy(thrdName+3, pThis->name, 20); dbgOutputTID((char*)thrdName); # if HAVE_PRCTL && defined PR_SET_NAME /* set thread name - we ignore if the call fails, has no harsh consequences... */ if(prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", pThis->name); } else { DBGPRINTF("set thread name to '%s'\n", thrdName); } # endif /* block all signals */ sigset_t sigSet; sigfillset(&sigSet); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); /* but ignore SIGTTN, which we (ab)use to signal the thread to shutdown -- rgerhards, 2009-07-20 */ sigemptyset(&sigSet); sigaddset(&sigSet, SIGTTIN); pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL); /* setup complete, we are now ready to execute the user code. We will not * regain control until the user code is finished, in which case we terminate * the thread. */ iRet = pThis->pUsrThrdMain(pThis); dbgprintf("thrdStarter: usrThrdMain %s - 0x%lx returned with iRet %d, exiting now.\n", pThis->name, (unsigned long) pThis->thrdID, iRet); /* signal master control that we exit (we do the mutex lock mostly to * keep the thread debugger happer, it would not really be necessary with * the logic we employ...) */ d_pthread_mutex_lock(&pThis->mutThrd); pThis->bIsActive = 0; pthread_cond_signal(&pThis->condThrdTerm); d_pthread_mutex_unlock(&pThis->mutThrd); ENDfunc pthread_exit(0); }
void lcd_print_dir_entry(uint16_t i) { char filename[16 + 1]; if (ep[i]->flags & E_DIR) lcd_puts_P(PSTR("DIR ")); else if (ep[i]->flags & E_IMAGE) lcd_puts_P(PSTR("IMG ")); else lcd_printf("%3u ", ep[i]->filesize); memset (filename, 0, sizeof(filename)); ustrncpy(filename, ep[i]->filename, (LCD_COLS - 4) > 16 ? 16 : LCD_COLS - 4); pet2asc((uint8_t *) filename); lcd_puts(filename); }
//***************************************************************************** // // Sets the value of a tStat structure based on a formatted string input. // //***************************************************************************** void StatSetVal(tStat *psStat, char *pcInputValue) { if((psStat->eValueType) == STRING) { ustrncpy(StatStringVal(*psStat), pcInputValue, MAX_STAT_STRING); } else if((psStat->eValueType == INT) || (psStat->eValueType == HEX)) { StatIntVal(*psStat) = ustrtoul(pcInputValue, NULL, 0); } }
uTCHAR *js_to_name(const DBWORD val, const _js_element *list, const DBWORD length) { BYTE index; static uTCHAR str[20]; umemset(str, 0x00, usizeof(str)); for (index = 0; index < length; index++) { if (val == list[index].value) { ustrncpy(str, list[index].name, usizeof(str)); return ((uTCHAR *) str); } } return ((uTCHAR *) list[0].name); }
uTCHAR *js_name_device(int dev) { static uTCHAR name[128]; uTCHAR path_dev[30]; int fd; umemset(name, 0x00, usizeof(name)); usnprintf(path_dev, usizeof(path_dev), uL("" JS_DEV_PATH "%d"), dev); fd = uopen(path_dev, O_RDONLY | O_NONBLOCK); if (uioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0) { ustrncpy(name, uL("Not connected"), usizeof(name)); } close(fd); return((uTCHAR *) name); }
/* Initialize the Signature Object */ void CSigScan::Init(unsigned char *sig, char *mask, size_t len) { is_set = 0; sig_len = len; sig_str = new unsigned char[sig_len]; ustrncpy(sig_str, sig, sig_len); sig_mask = new char[sig_len+2]; //Original line was "sig_mask = new char[sig_len+1];", but made my module fail with "invalid access to memory" (translated error message into English) @aVoN strncpy(sig_mask, mask, sig_len); sig_mask[sig_len+1] = 0; if(!base_addr) return ; // GetDllMemInfo() Failed if((sig_addr = FindSignature()) == NULL) return ; // FindSignature() Failed is_set = 1; // SigScan Successful! }
/* Initialize the Signature Object */ void CSigScan::Init(unsigned char *sig, char *mask, size_t len) { is_set = 0; sig_len = len; sig_str = new unsigned char[sig_len]; ustrncpy(sig_str, sig, sig_len); sig_mask = new char[sig_len+1]; strncpy(sig_mask, mask, sig_len); sig_mask[sig_len+1] = 0; if(!base_addr) return ; // GetDllMemInfo() Failed if((sig_addr = FindSignature()) == NULL) return ; // FindSignature() Failed is_set = 1; // SigScan Successful! }
int usubstitute_env(char *line, int max_len) { char *tmp_line; char *env_cpy; char *dollar_bracket; char *closing_bracket; char *pre_str; char *env_str; char *env_val; char *post_str; int pre_len, env_len, post_len, tot_len; tmp_line = (char *) umalloc(max_len); env_cpy = (char *) umalloc(max_len); memset(env_cpy, 0, max_len); /* * look for opening '$(' sequence */ while ((dollar_bracket = ustrstr(line, "$(")) != NULL) { pre_str = line; env_str = dollar_bracket + 2; if ((closing_bracket = strchr(env_str, ')')) == NULL) { /* * no closing bracket */ fprintf(stderr, "WARNING - uparams_read:substitute_env\n"); fprintf(stderr, "No closing bracket for env variable\n"); fprintf(stderr, "Reading '%s'", line); ufree(tmp_line); ufree(env_cpy); return (-1); } /* if ((closing_bracket = ... */ post_str = closing_bracket + 1; /* * load up env string and null terminate */ env_len = (int) (closing_bracket - env_str); strncpy(env_cpy, env_str, env_len ); env_cpy[env_len] = '\0'; /* * get env val */ if ((env_val = getenv(env_cpy)) == NULL) { /* * no env variable set */ fprintf(stderr, "WARNING - uparams_read:substitute_env\n"); fprintf(stderr, "Env variable '%s' not set\n", env_cpy); ufree(tmp_line); ufree(env_cpy); return (-1); } /* * compute total length after substitution */ pre_len = (int) (dollar_bracket - pre_str); env_len = strlen(env_val); post_len = strlen(post_str); tot_len = pre_len + env_len + post_len + 1; if (tot_len > max_len) { /* * substituted string too long */ fprintf(stderr, "WARNING - uparams_read:substitute_env\n"); fprintf(stderr, "Env str too long.\n"); fprintf(stderr, "Reading '%s'", line); ufree(tmp_line); ufree(env_cpy); return (-1); } /* if (tot_len > max_len) */ /* * set tmp line and copy over */ *dollar_bracket = '\0'; sprintf(tmp_line, "%s%s%s", pre_str, env_val, post_str); ustrncpy(line, tmp_line, max_len); } /* while */ ufree(tmp_line); ufree(env_cpy); return (0); }
//***************************************************************************** // // Send Data to the Screen starting at line index // default to start at line 2 // //***************************************************************************** void ScreenPayloadWrite(uint8_t * source, uint32_t length, uint32_t index) { uint32_t x=0; switch(index) { case 1: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine1,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine1,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } default: case 2: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine2,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine2,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } case 3: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine3,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine3,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } case 4: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine4,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine4,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } case 5: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine5,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine5,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } case 6: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine6,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine6,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } case 7: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine7,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine7,(char *)source+x, SCREEN_LINELENGTH); } x=x+SCREEN_LINELENGTH; } case 8: { if((length-x) < SCREEN_LINELENGTH) { ustrncpy(g_pcPayloadLine8,(char *)source+x, length-x); return; } else { ustrncpy(g_pcPayloadLine8,(char *)source+x, SCREEN_LINELENGTH); } } } return; }
/** * file_open - open a file on given secondary * @secondary: secondary address used in OPEN call * * This function opens the file named in command_buffer on the given * secondary address. All special names and prefixes/suffixed are handled * here, e.g. $/#/@/,S,W */ void file_open(uint8_t secondary) { buffer_t *buf; uint8_t i = 0; uint8_t recordlen = 0; /* If the secondary is already in use, close the existing buffer */ buf = find_buffer(secondary); if (buf != NULL) { /* FIXME: What should we do if an error occurs? */ cleanup_and_free_buffer(buf); } /* Assume everything will go well unless proven otherwise */ set_error(ERROR_OK); /* Strip 0x0d characters from end of name (C2BD-C2CA) */ if (command_length > 1) { if (command_buffer[command_length-1] == 0x0d) command_length -= 1; else if (command_buffer[command_length-2] == 0x0d) command_length -= 2; } /* Clear the remainder of the command buffer, simplifies parsing */ memset(command_buffer+command_length, 0, sizeof(command_buffer)-command_length); uart_trace(command_buffer,0,command_length); /* Direct access? */ if (command_buffer[0] == '#') { open_buffer(secondary); return; } /* Parse type+mode suffixes */ uint8_t *ptr = command_buffer; enum open_modes mode = OPEN_READ; uint8_t filetype = TYPE_DEL; while(i++ < 2 && *ptr && (ptr = ustrchr(ptr, ','))) { *ptr = 0; ptr++; switch (*ptr) { case 0: break; case 'R': /* Read */ mode = OPEN_READ; break; case 'W': /* Write */ mode = OPEN_WRITE; break; case 'A': /* Append */ mode = OPEN_APPEND; break; case 'M': /* Modify */ mode = OPEN_MODIFY; break; case 'D': /* DEL */ filetype = TYPE_DEL; break; case 'S': /* SEQ */ filetype = TYPE_SEQ; break; case 'P': /* PRG */ filetype = TYPE_PRG; break; case 'U': /* USR */ filetype = TYPE_USR; break; case 'L': /* REL */ filetype = TYPE_REL; mode = OPEN_WRITE; if((ptr = ustrchr(ptr, ','))) recordlen = *(++ptr); i = 2; // stop the scan break; } } /* Load directory? */ if (command_buffer[0] == '$') { load_directory(secondary); return; } /* Parse path+partition numbers */ uint8_t *fname; int8_t res; cbmdirent_t dent; path_t path; /* Parse path and file name */ if (parse_path(command_buffer, &path, &fname, 0)) return; #ifdef CONFIG_M2I /* For M2I only: Remove trailing spaces from name */ if (partition[path.part].fop == &m2iops) { res = ustrlen(fname); while (--res && fname[res] == ' ') fname[res] = 0; } #endif /* Filename matching */ if (opendir(&matchdh, &path)) return; do { res = next_match(&matchdh, fname, NULL, NULL, FLAG_HIDDEN, &dent); if (res > 0) /* Error, abort */ return; /* Don't match on DEL or DIR */ if ((dent.typeflags & TYPE_MASK) != TYPE_DEL && (dent.typeflags & TYPE_MASK) != TYPE_DIR) break; /* But do match if it's for writing */ if (mode == OPEN_WRITE || secondary == 1) break; } while (res == 0); if(res && filetype == TYPE_REL && !recordlen) { set_error(ERROR_SYNTAX_UNABLE); return; } /* If match found is a REL... */ if(!res && (dent.typeflags & TYPE_MASK) == TYPE_REL) { /* requested type must be REL or DEL */ if(filetype != TYPE_REL && filetype != TYPE_DEL) { set_error(ERROR_FILE_TYPE_MISMATCH); return; } filetype = TYPE_REL; mode = OPEN_MODIFY; } /* Force mode+type for secondaries 0/1 */ switch (secondary) { case 0: mode = OPEN_READ; if (filetype == TYPE_DEL) filetype = TYPE_PRG; break; case 1: mode = OPEN_WRITE; if (filetype == TYPE_DEL) filetype = TYPE_PRG; break; default: if (filetype == TYPE_DEL) filetype = TYPE_SEQ; } if (mode == OPEN_WRITE) { if (res == 0) { /* Match found */ if (command_buffer[0] == '@') { /* Make sure there is a free buffer to open the new file later */ if (!check_free_buffers()) { set_error(ERROR_NO_CHANNEL); return; } /* Copy dent because file_delete may change it */ cbmdirent_t dentcopy = dent; /* Rewrite existing file: Delete the old one */ if (file_delete(&path, &dentcopy) == 255) return; /* Force fatops to create a new name based on the (long) CBM- */ /* name instead of creating one with the old SFN and no LFN. */ if (dent.opstype == OPSTYPE_FAT || dent.opstype == OPSTYPE_FAT_X00) dent.pvt.fat.realname[0] = 0; } else { /* Write existing file without replacement: Raise error */ set_error(ERROR_FILE_EXISTS); return; } } else { /* Normal write or non-existing rewrite */ /* Doesn't exist: Copy name to dent */ memset(&dent, 0, sizeof(dent)); ustrncpy(dent.name, fname, CBM_NAME_LENGTH); set_error(ERROR_OK); // because first_match has set FNF } } else if (res != 0) { /* File not found */ set_error(ERROR_FILE_NOT_FOUND); return; } /* Grab a buffer */ buf = alloc_buffer(); if (!buf) return; buf->secondary = secondary; if(filetype == TYPE_REL) { display_filename_write(path.part,CBM_NAME_LENGTH,dent.name); open_rel(&path, &dent, buf, recordlen, (mode == OPEN_MODIFY)); return; } switch (mode) { case OPEN_MODIFY: case OPEN_READ: /* Modify is the same as read, but allows reading *ed files. */ /* FAT doesn't have anything equivalent, so both are mapped to READ */ display_filename_read(path.part,CBM_NAME_LENGTH,dent.name); open_read(&path, &dent, buf); break; case OPEN_WRITE: case OPEN_APPEND: display_filename_write(path.part,CBM_NAME_LENGTH,dent.name); open_write(&path, &dent, filetype, buf, (mode == OPEN_APPEND)); break; } }
//***************************************************************************** // // Given a pointer to a tStat and a destination string, this function will // print the value of the tStat to the string. // //***************************************************************************** void StatPrintValue(tStat *psStat, char *pcValueString) { char *pcSourceString; char pcPercentString[3]; uint32_t ui32CharValue; uint8_t ui8Index; // // Check the type of data that is stored in this psStat variable. // if((psStat->eValueType) == STRING) { // // If this is a string, perform a little processing to remove // percent-encoded characters. First, copy the original string pointer // for ease of use. // pcSourceString = StatStringVal(*psStat); // // Loop through the characters in the string one by one. // ui8Index = 0; while(*pcSourceString != 0) { // // If the character is a percent sign, calculate the correct // percent-encoding substitution. // if(*pcSourceString == '%') { // // The next two characters should be a hexadecimal // representation of the actual character that should be // printed. Convert them to an integer here. // ustrncpy(pcPercentString, (pcSourceString + 1), 2); pcPercentString[2] = 0; ui32CharValue = ustrtoul((pcPercentString), NULL, 16); // // Increment the source pointer past the escaped characters. // pcSourceString = pcSourceString + 3; // // Copy the converted value into the destination string. // pcValueString[ui8Index] = ui32CharValue; } else { // // If the character was not a percent sign, it can be copied // directly. // pcValueString[ui8Index] = *pcSourceString; pcSourceString++; } // // Increment the index. // ui8Index++; } pcValueString[ui8Index] = 0; } else if((psStat->eValueType) == INT) { // // If this is an integer value, just print the value as text into the // destination string. // usprintf(pcValueString, "%d", StatIntVal(*psStat)); } }
//***************************************************************************** // // Print a string to the screen and save it to the screen buffer. // //***************************************************************************** void WriteString(const char *pcString) { uint32_t ui32Size, ui32StrSize; char *pcCurLine; int32_t i32Idx; ui32StrSize = ustrlen(pcString); // // Check if the string requires scrolling the text in order to print. // if((g_ui32Line >= MAX_LINES) && (g_ui32Column == 0)) { // // Start redrawing at line 0. // g_ui32Line = 0; // // Print lines from the current position down first. // for(i32Idx = g_ui32CurrentLine + 1; i32Idx < MAX_LINES; i32Idx++) { GrStringDraw(&g_sContext, g_pcLines + (MAX_COLUMNS * i32Idx), ustrlen(g_pcLines + (MAX_COLUMNS * i32Idx)), DISPLAY_TEXT_BORDER_H, DISPLAY_BANNER_HEIGHT + DISPLAY_TEXT_BORDER + (g_ui32Line * GrFontHeightGet(g_psFontFixed6x8)), 1); g_ui32Line++; } // // If not already at the top then print the lines starting at the // top of the buffer. // if(g_ui32CurrentLine != 0) { for(i32Idx = 0; i32Idx < g_ui32CurrentLine; i32Idx++) { GrStringDraw(&g_sContext, g_pcLines + (MAX_COLUMNS * i32Idx), ustrlen(g_pcLines + (MAX_COLUMNS * i32Idx)), DISPLAY_TEXT_BORDER_H, DISPLAY_BANNER_HEIGHT + DISPLAY_TEXT_BORDER + (g_ui32Line * GrFontHeightGet(g_psFontFixed6x8)), 1); g_ui32Line++; } } } // // Save the current line pointer to use in references below. // pcCurLine = g_pcLines + (MAX_COLUMNS * g_ui32CurrentLine); if(g_ui32Column + ui32StrSize >= MAX_COLUMNS - 1) { ui32Size = MAX_COLUMNS - g_ui32Column - 1; } else { ui32Size = ui32StrSize; } // // Handle the case where the string has a new line at the end. // if(pcString[ui32StrSize-1] == '\n') { // // Make sure that this is not a single new line. // if(ui32Size > 0 ) { // // Copy the string into the screen buffer. // ustrncpy(pcCurLine + g_ui32Column, pcString, ui32Size - 1); } // // If this is the start of a new line then clear out the rest of the // line by writing spaces to the end of the line. // if(g_ui32Column == 0) { // // Clear out the string with spaces to overwrite any existing // characters with spaces. // for(i32Idx = ui32Size - 1; i32Idx < MAX_COLUMNS; i32Idx++) { pcCurLine[i32Idx] = ' '; } } // // Null terminate the string. // pcCurLine[g_ui32Column + MAX_COLUMNS - 1] = 0; // // Draw the new string. // GrStringDraw(&g_sContext, pcCurLine + g_ui32Column, ui32Size - 1, DISPLAY_TEXT_BORDER_H + (GrFontMaxWidthGet(g_psFontFixed6x8) * g_ui32Column), DISPLAY_BANNER_HEIGHT + DISPLAY_TEXT_BORDER + (g_ui32Line * GrFontHeightGet(g_psFontFixed6x8)), 1); // // Increment the line values and reset the column to 0. // g_ui32Line++; g_ui32CurrentLine++; if(g_ui32CurrentLine >= MAX_LINES) { g_ui32CurrentLine = 0; } g_ui32Column = 0; } else { // // Copy the string into the screen buffer. // ustrncpy(pcCurLine + g_ui32Column, pcString, ui32Size); // // See if this was the first string draw on this line. // if(g_ui32Column == 0) { // // Pad the rest of the string with spaces to overwrite any existing // characters with spaces. // for(i32Idx = ui32Size; i32Idx < MAX_COLUMNS - 1; i32Idx++) { pcCurLine[i32Idx] = ' '; } // // Draw the new string. // GrStringDraw(&g_sContext, pcCurLine + g_ui32Column, MAX_COLUMNS - 1, DISPLAY_TEXT_BORDER_H + (GrFontMaxWidthGet(g_psFontFixed6x8) * g_ui32Column), DISPLAY_BANNER_HEIGHT + DISPLAY_TEXT_BORDER + (g_ui32Line * GrFontHeightGet(g_psFontFixed6x8)), 1); } else { // // Draw the new string. // GrStringDraw(&g_sContext, pcCurLine + g_ui32Column, g_ui32Column + ui32Size, DISPLAY_TEXT_BORDER_H + (GrFontMaxWidthGet(g_psFontFixed6x8) * g_ui32Column), DISPLAY_BANNER_HEIGHT + DISPLAY_TEXT_BORDER + (g_ui32Line * GrFontHeightGet(g_psFontFixed6x8)), 1); } // // Update the current column. // g_ui32Column += ui32Size; } }
void cmd_line_parse(int argc, uTCHAR **argv) { QStringList splitted; QString arg, key, skey, value, exe = QFileInfo(uQString(argv[0])).baseName(); int opt = 0; for (int a = 1; a < argc; a++) { arg = uQString(argv[a]); splitted = arg.split("="); key = QString(splitted.at(0)); if (key.startsWith("--") || key.startsWith("-")) { key = key.replace("-", ""); for (unsigned int b = 0; b < LENGTH(opt_long); b++) { if ((opt_long[b].lopt == key) || (opt_long[b].sopt == key)) { skey = opt_long[b].sopt; if (opt_long[b].ra == req_arg) { if (splitted.count() > 1) { value = QString(splitted.at(1)); } else { if ((a + 1) >= argc) { QMessageBox::warning(0, "Error", QString("%1: the option needs an arguments -- \"%2\"").arg(exe, key)); usage(exe); } else { value = uQString(argv[++a]); } } } opt = (*((char *) skey.toLatin1().constData())); } } } else { umemset(info.rom_file, 0x00, usizeof(info.rom_file)); ustrncpy(info.rom_file, uQStringCD(key), usizeof(info.rom_file) - 1); continue; } switch (opt) { case 0: // long options if (key == "swap-duty") { set_int(cfg_from_file.swap_duty, SET_SWAP_DUTY); } else if (key == "swap-emphasis") { set_int(cfg_from_file.disable_swap_emphasis_pal, SET_SWAP_EMPHASIS_PAL); } else if (key == "portable") { // l'ho gia' controllato quindi qui non faccio niente } else if (key == "txt-on-screen") { set_int(cfg_from_file.txt_on_screen, SET_TEXT_ON_SCREEN); } else if (key == "input-display") { set_int(cfg_from_file.input_display, SET_INPUT_DISPLAY); } else if (key == "disable-tv-noise") { set_int(cfg_from_file.disable_tv_noise, SET_DISABLE_TV_NOISE); } else if (key == "disable-sepia") { set_int(cfg_from_file.disable_sepia_color, SET_DISABLE_SEPIA_PAUSE); #if defined (WITH_OPENGL) } else if (key == "disable-srgb-fbo") { set_int(cfg_from_file.disable_srgb_fbo, SET_DISABLE_SRGB_FBO); #endif } else if (key == "overscan-brd-ntsc") { set_oscan(SET_OVERSCAN_BRD_NTSC, 0); } else if (key == "overscan-brd-pal") { set_oscan(SET_OVERSCAN_BRD_PAL, 1); } else if (key == "par-soft-stretch") { set_int(cfg_from_file.PAR_soft_stretch, SET_PAR_SOFT_STRETCH); } else if (key == "hide-sprites") { set_int(cfg_from_file.hide_sprites, SET_HIDE_SPRITES); } else if (key == "hide-background") { set_int(cfg_from_file.hide_background, SET_HIDE_BACKGROUND); } else if (key == "unlimited-sprites") { set_int(cfg_from_file.unlimited_sprites, SET_UNLIMITED_SPRITES); } else if (key == "save-battery-ram-file") { set_int(cfg_from_file.save_battery_ram_file, SET_BATTERY_RAM_FILE_EVEY_TOT); } else if (key == "background-pause") { set_int(cfg_from_file.bck_pause, SET_BCK_PAUSE); } else if (key == "language") { set_int(cfg_from_file.language, SET_GUI_LANGUAGE); } else if (key == "disable-new-menu") { set_int(cfg_from_file.disable_new_menu, SET_GUI_DISABLE_NEW_MENU); } break; case 'a': set_int(cfg_from_file.apu.channel[APU_MASTER], SET_AUDIO); break; case 'b': set_int(cfg_from_file.audio_buffer_factor, SET_AUDIO_BUFFER_FACTOR); break; case 'c': set_int(cfg_from_file.channels_mode, SET_CHANNELS); break; case 'd': cfg_from_file.stereo_delay = set_double(5); break; case 'f': set_int(cfg_from_file.fps, SET_FPS); break; case 'g': set_int(cfg_from_file.cheat_mode, SET_CHEAT_MODE); break; case 'h': case '?': usage(exe); break; case 'V': { if (!info.portable) { fprintf(stdout, "%s %s\n", NAME, VERSION); } else { fprintf(stdout, "Portable %s %s\n", NAME, VERSION); } emu_quit(EXIT_SUCCESS); break; } case 'k': set_int(cfg_from_file.frameskip, SET_FRAMESKIP); break; case 'i': set_int(cfg_from_file.filter, SET_FILTER); break; case 'l': set_int(cfg_from_file.samplerate, SET_SAMPLERATE); break; case 'm': set_int(cfg_from_file.mode, SET_MODE); break; case 'n': set_int(cfg_from_file.ntsc_format, SET_NTSC_FORMAT); break; case 'o': set_int(cfg_from_file.oscan, SET_OVERSCAN_DEFAULT); break; case 'p': set_int(cfg_from_file.palette, SET_PALETTE); break; case 'q': set_int(cfg_from_file.audio_quality, SET_AUDIO_QUALITY); break; #if defined (WITH_OPENGL) case 'r': set_int(cfg_from_file.render, SET_RENDERING); gfx_set_render(cfg_from_file.render); break; #endif case 's': set_int(cfg_from_file.scale, SET_SCALE); gfx.scale_before_fscreen = cfg_from_file.scale; break; case 't': { int rc = settings_val_to_int(SET_STRETCH_FULLSCREEN, oarg); if (rc >= 0) { cfg_from_file.scale = !rc; } } break; case 'u': set_int(cfg_from_file.fullscreen, SET_FULLSCREEN); break; case 'v': set_int(cfg_from_file.vsync, SET_VSYNC); break; case 'e': set_int(cfg_from_file.pixel_aspect_ratio, SET_PAR); break; case 'j': set_int(cfg_from_file.interpolation, SET_INTERPOLATION); break; default: break; } } }
static rsRetVal dynstats_addBucketMetrics(dynstats_buckets_t *bkts, dynstats_bucket_t *b, const uchar* name) { uchar *metric_name_buff, *metric_suffix; const uchar *suffix_litteral; int name_len; DEFiRet; name_len = ustrlen(name); CHKmalloc(metric_name_buff = malloc((name_len + DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar))); ustrncpy(metric_name_buff, name, name_len); metric_suffix = metric_name_buff + name_len; *metric_suffix = DYNSTATS_METRIC_NAME_SEPARATOR; metric_suffix++; suffix_litteral = UCHAR_CONSTANT("ops_overflow"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrOpsOverflow), &b->pOpsOverflowCtr, 1)); suffix_litteral = UCHAR_CONSTANT("new_metric_add"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrNewMetricAdd), &b->pNewMetricAddCtr, 1)); suffix_litteral = UCHAR_CONSTANT("no_metric"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrNoMetric, b->mutCtrNoMetric); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrNoMetric), &b->pNoMetricCtr, 1)); suffix_litteral = UCHAR_CONSTANT("metrics_purged"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrMetricsPurged, b->mutCtrMetricsPurged); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrMetricsPurged), &b->pMetricsPurgedCtr, 1)); suffix_litteral = UCHAR_CONSTANT("ops_ignored"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrOpsIgnored, b->mutCtrOpsIgnored); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrOpsIgnored), &b->pOpsIgnoredCtr, 1)); suffix_litteral = UCHAR_CONSTANT("purge_triggered"); ustrncpy(metric_suffix, suffix_litteral, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrPurgeTriggered, b->mutCtrPurgeTriggered); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrPurgeTriggered), &b->pPurgeTriggeredCtr, 1)); finalize_it: free(metric_name_buff); if (iRet != RS_RET_OK) { if (b->pOpsOverflowCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pOpsOverflowCtr); } if (b->pNewMetricAddCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pNewMetricAddCtr); } if (b->pNoMetricCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pNoMetricCtr); } if (b->pMetricsPurgedCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pMetricsPurgedCtr); } if (b->pOpsIgnoredCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pOpsIgnoredCtr); } if (b->pPurgeTriggeredCtr != NULL) { statsobj.DestructCounter(bkts->global_stats, b->pPurgeTriggeredCtr); } } RETiRet; }
//***************************************************************************** // //! A simple vsnprintf function supporting \%c, \%d, \%p, \%s, \%u, \%x, and //! \%X. //! //! \param pcBuf points to the buffer where the converted string is stored. //! \param ulSize is the size of the buffer. //! \param pcString is the format string. //! \param vaArgP is the list of optional arguments, which depend on the //! contents of the format string. //! //! This function is very similar to the C library <tt>vsnprintf()</tt> //! function. Only the following formatting characters are supported: //! //! - \%c to print a character //! - \%d or \%i to print a decimal value //! - \%s to print a string //! - \%u to print an unsigned decimal value //! - \%x to print a hexadecimal value using lower case letters //! - \%X to print a hexadecimal value using lower case letters (not upper case //! letters as would typically be used) //! - \%p to print a pointer as a hexadecimal value //! - \%\% to print out a \% character //! //! For \%d, \%i, \%p, \%s, \%u, \%x, and \%X, an optional number may reside //! between the \% and the format character, which specifies the minimum number //! of characters to use for that value; if preceded by a 0 then the extra //! characters will be filled with zeros instead of spaces. For example, //! ``\%8d'' will use eight characters to print the decimal value with spaces //! added to reach eight; ``\%08d'' will use eight characters as well but will //! add zeroes instead of spaces. //! //! The type of the arguments after \e pcString must match the requirements of //! the format string. For example, if an integer was passed where a string //! was expected, an error of some kind will most likely occur. //! //! The \e ulSize parameter limits the number of characters that will be stored //! in the buffer pointed to by \e pcBuf to prevent the possibility of a buffer //! overflow. The buffer size should be large enough to hold the expected //! converted output string, including the null termination character. //! //! The function will return the number of characters that would be converted //! as if there were no limit on the buffer size. Therefore it is possible for //! the function to return a count that is greater than the specified buffer //! size. If this happens, it means that the output was truncated. //! //! \return Returns the number of characters that were to be stored, not //! including the NULL termination character, regardless of space in the //! buffer. // //***************************************************************************** int uvsnprintf(char *pcBuf, unsigned long ulSize, const char *pcString, va_list vaArgP) { unsigned long ulIdx, ulValue, ulCount, ulBase, ulNeg; char *pcStr, cFill; int iConvertCount = 0; // // Check the arguments. // ASSERT(pcString != 0); ASSERT(pcBuf != 0); ASSERT(ulSize != 0); // // Adjust buffer size limit to allow one space for null termination. // if(ulSize) { ulSize--; } // // Initialize the count of characters converted. // iConvertCount = 0; // // Loop while there are more characters in the format string. // while(*pcString) { // // Find the first non-% character, or the end of the string. // for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0'); ulIdx++) { } // // Write this portion of the string to the output buffer. If there are // more characters to write than there is space in the buffer, then // only write as much as will fit in the buffer. // if(ulIdx > ulSize) { ustrncpy(pcBuf, pcString, ulSize); pcBuf += ulSize; ulSize = 0; } else { ustrncpy(pcBuf, pcString, ulIdx); pcBuf += ulIdx; ulSize -= ulIdx; } // // Update the conversion count. This will be the number of characters // that should have been written, even if there was not room in the // buffer. // iConvertCount += ulIdx; // // Skip the portion of the format string that was written. // pcString += ulIdx; // // See if the next character is a %. // if(*pcString == '%') { // // Skip the %. // pcString++; // // Set the digit count to zero, and the fill character to space // (that is, to the defaults). // ulCount = 0; cFill = ' '; // // It may be necessary to get back here to process more characters. // Goto's aren't pretty, but effective. I feel extremely dirty for // using not one but two of the beasts. // again: // // Determine how to handle the next character. // switch(*pcString++) { // // Handle the digit characters. // case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { // // If this is a zero, and it is the first digit, then the // fill character is a zero instead of a space. // if((pcString[-1] == '0') && (ulCount == 0)) { cFill = '0'; } // // Update the digit count. // ulCount *= 10; ulCount += pcString[-1] - '0'; // // Get the next character. // goto again; } // // Handle the %c command. // case 'c': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Copy the character to the output buffer, if there is // room. Update the buffer size remaining. // if(ulSize != 0) { *pcBuf++ = (char)ulValue; ulSize--; } // // Update the conversion count. // iConvertCount++; // // This command has been handled. // break; } // // Handle the %d and %i commands. // case 'd': case 'i': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // If the value is negative, make it positive and indicate // that a minus sign is needed. // if((long)ulValue < 0) { // // Make the value positive. // ulValue = -(long)ulValue; // // Indicate that the value is negative. // ulNeg = 1; } else { // // Indicate that the value is positive so that a // negative sign isn't inserted. // ulNeg = 0; } // // Set the base to 10. // ulBase = 10; // // Convert the value to ASCII. // goto convert; } // // Handle the %s command. // case 's': { // // Get the string pointer from the varargs. // pcStr = va_arg(vaArgP, char *); // // Determine the length of the string. // for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) { } // // Update the convert count to include any padding that // should be necessary (regardless of whether we have space // to write it or not). // if(ulCount > ulIdx) { iConvertCount += (ulCount - ulIdx); } // // Copy the string to the output buffer. Only copy as much // as will fit in the buffer. Update the output buffer // pointer and the space remaining. // if(ulIdx > ulSize) { ustrncpy(pcBuf, pcStr, ulSize); pcBuf += ulSize; ulSize = 0; } else { ustrncpy(pcBuf, pcStr, ulIdx); pcBuf += ulIdx; ulSize -= ulIdx; // // Write any required padding spaces assuming there is // still space in the buffer. // if(ulCount > ulIdx) { ulCount -= ulIdx; if(ulCount > ulSize) { ulCount = ulSize; } ulSize =- ulCount; while(ulCount--) { *pcBuf++ = ' '; } } } // // Update the conversion count. This will be the number of // characters that should have been written, even if there // was not room in the buffer. // iConvertCount += ulIdx; // // This command has been handled. // break; } // // Handle the %u command. // case 'u': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Set the base to 10. // ulBase = 10; // // Indicate that the value is positive so that a minus sign // isn't inserted. // ulNeg = 0; // // Convert the value to ASCII. // goto convert; } // // Handle the %x and %X commands. Note that they are treated // identically; that is, %X will use lower case letters for a-f // instead of the upper case letters is should use. We also // alias %p to %x. // case 'x': case 'X': case 'p': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Set the base to 16. // ulBase = 16; // // Indicate that the value is positive so that a minus sign // isn't inserted. // ulNeg = 0; // // Determine the number of digits in the string version of // the value. // convert: for(ulIdx = 1; (((ulIdx * ulBase) <= ulValue) && (((ulIdx * ulBase) / ulBase) == ulIdx)); ulIdx *= ulBase, ulCount--) { } // // If the value is negative, reduce the count of padding // characters needed. // if(ulNeg) { ulCount--; } // // If the value is negative and the value is padded with // zeros, then place the minus sign before the padding. // if(ulNeg && (ulSize != 0) && (cFill == '0')) { // // Place the minus sign in the output buffer. // *pcBuf++ = '-'; ulSize--; // // Update the conversion count. // iConvertCount++; // // The minus sign has been placed, so turn off the // negative flag. // ulNeg = 0; } // // See if there are more characters in the specified field // width than there are in the conversion of this value. // if((ulCount > 1) && (ulCount < 65536)) { // // Loop through the required padding characters. // for(ulCount--; ulCount; ulCount--) { // // Copy the character to the output buffer if there // is room. // if(ulSize != 0) { *pcBuf++ = cFill; ulSize--; } // // Update the conversion count. // iConvertCount++; } } // // If the value is negative, then place the minus sign // before the number. // if(ulNeg && (ulSize != 0)) { // // Place the minus sign in the output buffer. // *pcBuf++ = '-'; ulSize--; // // Update the conversion count. // iConvertCount++; } // // Convert the value into a string. // for(; ulIdx; ulIdx /= ulBase) { // // Copy the character to the output buffer if there is // room. // if(ulSize != 0) { *pcBuf++ = g_pcHex[(ulValue / ulIdx) % ulBase]; ulSize--; } // // Update the conversion count. // iConvertCount++; } // // This command has been handled. // break; } // // Handle the %% command. // case '%': { // // Simply write a single %. // if(ulSize != 0) { *pcBuf++ = pcString[-1]; ulSize--; } // // Update the conversion count. // iConvertCount++; // // This command has been handled. // break; } // // Handle all other commands. // default: { // // Indicate an error. // if(ulSize >= 5) { ustrncpy(pcBuf, "ERROR", 5); pcBuf += 5; ulSize -= 5; } else { ustrncpy(pcBuf, "ERROR", ulSize); pcBuf += ulSize; ulSize = 0; } // // Update the conversion count. // iConvertCount += 5; // // This command has been handled. // break; } } } }
void menu_browse_files(void) { buffer_t *buf; buffer_t *buf_tbl; buffer_t *buf_cur; buffer_t *first_buf; path_t path; cbmdirent_t dent; uint16_t entries; uint8_t entry_num; bool fat_filesystem; uint8_t i; uint8_t my; uint16_t mp; bool action; uint16_t stack_mp[MAX_LASTPOS]; uint8_t stack_my[MAX_LASTPOS]; uint8_t pos_stack; uint8_t save_active_buffers; pos_stack = 0; memset(stack_mp, 0, sizeof(stack_mp)); memset(stack_my, 0, sizeof(stack_my)); save_active_buffers = active_buffers; start: lcd_clear(); lcd_puts_P(PSTR("Reading...")); buf = buf_tbl = buf_cur = first_buf = NULL; entries = entry_num = mp = 0; fat_filesystem = false; // Allocate one buffer, used to read a single directory entry if ((buf = alloc_system_buffer()) == NULL) return; // Allocate buffers with continuous data segments // Stores pointers to directory entries for qsort if ((buf_tbl = alloc_linked_buffers(CONFIG_DIR_BUFFERS)) == NULL) return; // Buffers to store the actual diretory entries. // Whilst the directory grows, new buffers get allocated and linked if ((buf_cur = alloc_system_buffer()) == NULL) return; first_buf = buf_cur; // Allocating buffers affects the LEDs set_busy_led(false); set_dirty_led(true); path.part = current_part; path.dir = partition[path.part].current_dir; uart_trace(&path.dir, 0, sizeof(dir_t)); uart_putcrlf(); uart_flush(); if (opendir(&buf->pvt.dir.dh, &path)) return; for (;;) { if (next_match(&buf->pvt.dir.dh, buf->pvt.dir.matchstr, buf->pvt.dir.match_start, buf->pvt.dir.match_end, buf->pvt.dir.filetype, &dent) == 0) { uint8_t e_flags = 0; if (dent.opstype == OPSTYPE_FAT) { fat_filesystem = true; if (check_imageext(dent.pvt.fat.realname) != IMG_UNKNOWN) e_flags |= E_IMAGE; } // Current block full? if (entry_num == ENTRIES_PER_BLOCK) { entry_num = 0; buffer_t *old_buf = buf_cur; if ((buf_cur = alloc_system_buffer()) == NULL) { printf("alloc buf_cur failed, %d entries", entries); goto cleanup; } set_busy_led(false); set_dirty_led(true); buf_cur->pvt.buffer.next = NULL; old_buf->pvt.buffer.next = buf_cur; } // Store entry ep[entries] = (entry_t *) (buf_cur->data + entry_num * sizeof(entry_t)); ustrncpy(ep[entries]->filename, dent.name, 16); ep[entries]->filesize = dent.blocksize; if ((dent.typeflags & EXT_TYPE_MASK) == TYPE_DIR) e_flags |= E_DIR; ep[entries]->flags = e_flags; entries++; entry_num++; } else { // No more directory entries to read break; } } printf("%d entries\r\n", entries); if (fat_filesystem) qsort(ep, entries, sizeof(entry_t*), compare); for (uint16_t i = 0; i < entries; i++) { printf("%3u: ", i); if (ep[i]->flags & E_DIR) uart_puts_P(PSTR(" DIR ")); else if (ep[i]->flags & E_IMAGE) uart_puts_P(PSTR(" IMG ")); else printf("%4u ", ep[i]->filesize); uint8_t filename[16 + 1]; ustrncpy(filename, ep[i]->filename, 16); filename[16] = '\0'; pet2asc(filename); printf("%s\r\n", filename); uart_flush(); } uart_putcrlf(); #define DIRNAV_OFFSET 2 #define NAV_ABORT 0 #define NAV_PARENT 1 mp = stack_mp[pos_stack]; my = stack_my[pos_stack]; printf("mp set to %d\r\n", mp); if (mp < (LCD_LINES - 1)) my = mp; else my = 0; action = false; for (i=0; i < MAX_LASTPOS; i++) { if (pos_stack == i) uart_putc('>'); printf("%d ", stack_mp[i]); } uart_putcrlf(); for (;;) { lcd_clear(); for (i = 0; i < LCD_LINES; i++) { lcd_locate(0, i); int8_t y = mp - my + i; if (y < 0) return; // should not happen! if (y < DIRNAV_OFFSET) { rom_menu_browse(y); } else { y -= DIRNAV_OFFSET; if (y >= entries) { lcd_puts_P(PSTR("-- End of dir --")); break; } else { lcd_print_dir_entry(y); } } } lcd_cursor(true); for (;;) { lcd_locate(0, my); //printf("mp: %u my: %u\r\n", mp, my); //while (!get_key_state(KEY_ANY)); if (get_key_autorepeat(KEY_PREV)) { if (mp > 0) { --mp; if (my > 0) --my; else { my = LCD_LINES - 1; if (mp < LCD_LINES) { while ((mp - my) >= DIRNAV_OFFSET) { --my; // TODO: is this really necessary? uart_puts_P(PSTR("my fixed\r\n")); } } break; } } else { my = LCD_LINES - 2; mp = entries + DIRNAV_OFFSET - 1; break; } } if (get_key_autorepeat(KEY_NEXT)) { if (mp < (entries -1 + DIRNAV_OFFSET)) { ++mp; if (my < (LCD_LINES - 1)) ++my; else { my = 0; break; } } else { mp = 0; my = 0; break; } } if (get_key_press(KEY_SEL)) { action = true; break; } } lcd_cursor(false); if (!action) continue; if (mp == NAV_ABORT) goto cleanup; if (mp == NAV_PARENT) { uart_puts_P(PSTR("CD_\r\n")); ustrcpy_P(command_buffer, PSTR("CD_")); command_length = 3; parse_doscommand(); clear_command_buffer(); stack_mp[pos_stack] = 0; stack_my[pos_stack] = 0; if (pos_stack > 0) --pos_stack; printf("pos_stack set to %d\r\n", pos_stack); if (current_error != ERROR_OK) goto cleanup; goto reread; } if (ep[mp - DIRNAV_OFFSET]->flags & E_DIR || ep[mp - DIRNAV_OFFSET]->flags & E_IMAGE) { clear_command_buffer(); ustrcpy_P(command_buffer, PSTR("CD:")); ustrncpy(command_buffer + 3, ep[mp - DIRNAV_OFFSET]->filename, 16); command_length = ustrlen(command_buffer); parse_doscommand(); clear_command_buffer(); if (current_error != ERROR_OK) goto cleanup; if (pos_stack < MAX_LASTPOS) { stack_mp[pos_stack] = mp; stack_my[pos_stack++] = my; printf("pos_stack set to %d\r\n", pos_stack); } goto reread; } } reread: free_buffer(buf); buffer_t *p = buf_tbl; do { p->allocated = 0; p = p->pvt.buffer.next; } while (p != NULL); p = first_buf; if (p != NULL) do { p->allocated = 0; p = p->pvt.buffer.next; } while (p != NULL); set_busy_led(false); set_dirty_led(true); active_buffers = save_active_buffers; if (mp == NAV_ABORT) return; goto start; cleanup: mp = NAV_ABORT; goto reread; }