// factory function CommandActuator* CreateCommandActuator(const char* command) { CommandActuator* act = NULL; int32 argc; char** argv = ParseArgvFromString(command, argc); if (command[0] == '*') { if (argc > 0) { char* c = argv[0] + 1; if (strcmp(c, "InsertString") == 0) act = new KeyStrokeSequenceCommandActuator(argc, argv); else if (strcmp(c, "MoveMouse") == 0) act = new MoveMouseByCommandActuator(argc, argv); else if (strcmp(c, "MoveMouseTo") == 0) act = new MoveMouseToCommandActuator(argc, argv); else if (strcmp(c, "MouseButton") == 0) act = new MouseButtonCommandActuator(argc, argv); else if (strcmp(c, "LaunchHandler") == 0) act = new MIMEHandlerCommandActuator(argc, argv); else if (strcmp(c, "Multi") == 0) act = new MultiCommandActuator(argc, argv); else if (strcmp(c, "MouseDown") == 0) act = new MouseDownCommandActuator(argc, argv); else if (strcmp(c, "MouseUp") == 0) act = new MouseUpCommandActuator(argc, argv); else if (strcmp(c, "SendMessage") == 0) act = new SendMessageCommandActuator(argc, argv); else act = new BeepCommandActuator(argc, argv); } } else act = new LaunchCommandActuator(argc, argv); FreeArgv(argv); return act; }
bool ShortcutsSpec::_AttemptTabCompletion() { bool ret = false; int32 argc; char** argv = ParseArgvFromString(fCommand, argc); if (argc > 0) { // Try to complete the path partially expressed in the last argument! char* arg = argv[argc - 1]; char* fileFragment = strrchr(arg, '/'); if (fileFragment) { const char* directoryName = (fileFragment == arg) ? "/" : arg; *fileFragment = '\0'; fileFragment++; int fragLen = strlen(fileFragment); BDirectory dir(directoryName); if (dir.InitCheck() == B_NO_ERROR) { BEntry nextEnt; BPath nextPath; BList matchList; int maxEntryLen = 0; // Read in all the files in the directory whose names start // with our fragment. while (dir.GetNextEntry(&nextEnt) == B_NO_ERROR) { if (nextEnt.GetPath(&nextPath) == B_NO_ERROR) { char* filePath = strrchr(nextPath.Path(), '/') + 1; if (strncmp(filePath, fileFragment, fragLen) == 0) { int len = strlen(filePath); if (len > maxEntryLen) maxEntryLen = len; char* newStr = new char[len + 1]; strcpy(newStr, filePath); matchList.AddItem(newStr); } } } // Now slowly extend our keyword to its full length, counting // numbers of matches at each step. If the match list length // is 1, we can use that whole entry. If it's greater than one // , we can use just the match length. int matchLen = matchList.CountItems(); if (matchLen > 0) { int i; BString result(fileFragment); for (i = fragLen; i < maxEntryLen; i++) { // See if all the matching entries have the same letter // in the next position... if so, we can go farther. char commonLetter = '\0'; for (int j = 0; j < matchLen; j++) { char nextLetter = GetLetterAt( (char*)matchList.ItemAt(j), i); if (commonLetter == '\0') commonLetter = nextLetter; if ((commonLetter != '\0') && (commonLetter != nextLetter)) { commonLetter = '\0';// failed; beep(); break; } } if (commonLetter == '\0') break; else result.Append(commonLetter, 1); } // Free all the strings we allocated for (int k = 0; k < matchLen; k++) delete [] ((char*)matchList.ItemAt(k)); DoStandardEscapes(result); BString wholeLine; for (int l = 0; l < argc - 1; l++) { wholeLine += argv[l]; wholeLine += " "; } BString file(directoryName); DoStandardEscapes(file); if (directoryName[strlen(directoryName) - 1] != '/') file += "/"; file += result; // Remove any trailing slash... const char* fileStr = file.String(); if (fileStr[strlen(fileStr)-1] == '/') file.RemoveLast("/"); // And re-append it iff the file is a dir. BDirectory testFileAsDir(file.String()); if ((strcmp(file.String(), "/") != 0) && (testFileAsDir.InitCheck() == B_NO_ERROR)) file.Append("/"); wholeLine += file; SetCommand(wholeLine.String()); ret = true; } } *(fileFragment - 1) = '/'; } } FreeArgv(argv); return ret; }