/* * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab * Copyright (C) 2011 - DIGITEO - Karim Mamode * * This file must be used under the terms of the CeCILL. * This source file is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt */ #include #include #include #include #include #include #include "charEncoding.h" #include "completion.h" #include "autoCompletionCli.h" #include "completeLine.h" #include "cliDisplayManagement.h" #include "freeArrayOfString.h" #include "cliPrompt.h" #include "MALLOC.h" #include "completion.h" #include "getPartLine.h" #include "getCommonPart.h" #include "localization.h" #include "scilabmode.h" #include "sciprint.h" #include "HistoryManager.h" #include "ConsoleRead.h" #include "SetConsolePrompt.h" #include "TermReadAndProcess.h" #include "sciquit.h" #include "getCommonPart.h" static void doCompletion(char **wk_buf, unsigned int *cursor, unsigned int *cursor_max); static char *getLineBeforeCaret(char *wk_buf, unsigned int *cursor); static char *getLineAfterCaret(char *wk_buf, unsigned int *cursor, unsigned int *cursor_max); static void backspace(int n); static void erase_nchar(int n); static void TermCompletionOnFiles(char **dictionaryFiles, int sizedictionaryFiles, char *lineBeforeCaret, char *lineAfterCaret, char *filePattern, char *defaultPattern, char **wk_buf, unsigned int *cursor, unsigned int *cursor_max); static int CopyLineAtPrompt(char **wk_buf, char *line, unsigned int *cursor, unsigned int *cursor_max); static void TermCompletionOnAll(char *lineBeforeCaret, char *lineAfterCaret, char *defaultPattern, char **wk_buf, unsigned int *cursor, unsigned int *cursor_max); static void displayCompletionDictionary(char **dictionary, int sizedictionary, char *namedictionary); static char **concatenateStrings(int *sizearrayofstring, char *string1, char *string2, char *string3, char *string4, char *string5); /* Autocompletion in NW/NWNI */ void autoCompletionInConsoleMode(wchar_t ** commandLine, unsigned int *cursorLocation) { char *multiByteString = NULL; wchar_t *wideString = NULL; int sizeToAlloc = 0; unsigned int nbrCharInString; multiByteString = wide_string_to_UTF8(*commandLine); nbrCharInString = wcslen(*commandLine); doCompletion(&multiByteString, cursorLocation, &nbrCharInString); wideString = to_wide_string(multiByteString); /* Copy the new string in a buffer wich size is a multiple of 1024 */ sizeToAlloc = 1024 * (wcslen(wideString) / 1024 + 1); FREE(*commandLine); *commandLine = MALLOC(sizeof(**commandLine) * sizeToAlloc); wcscpy(*commandLine, wideString); FREE(wideString); FREE(multiByteString); } static void doCompletion(char **wk_buf, unsigned int *cursor, unsigned int *cursor_max) { char *LineBeforeCaret = getLineBeforeCaret(*wk_buf, cursor); char *LineAfterCaret = getLineAfterCaret(*wk_buf, cursor, cursor_max); char *fileSearchedPattern = getFilePartLevel(LineBeforeCaret); char *SearchedPattern = getPartLevel(LineBeforeCaret); char **completionDictionaryFiles = NULL; int sizecompletionDictionaryFiles = 0; completionDictionaryFiles = completionOnFiles(fileSearchedPattern, &sizecompletionDictionaryFiles); if (completionDictionaryFiles) { TermCompletionOnFiles(completionDictionaryFiles, sizecompletionDictionaryFiles, LineBeforeCaret, LineAfterCaret, fileSearchedPattern, SearchedPattern, wk_buf, cursor, cursor_max); freeArrayOfString(completionDictionaryFiles, sizecompletionDictionaryFiles); } else { TermCompletionOnAll(LineBeforeCaret, LineAfterCaret, SearchedPattern, wk_buf, cursor, cursor_max); } if (LineBeforeCaret) { FREE(LineBeforeCaret); LineBeforeCaret = NULL; } if (LineAfterCaret) { FREE(LineAfterCaret); LineAfterCaret = NULL; } if (fileSearchedPattern) { FREE(fileSearchedPattern); fileSearchedPattern = NULL; } if (SearchedPattern) { FREE(SearchedPattern); SearchedPattern = NULL; } } static char *getLineBeforeCaret(char *wk_buf, unsigned int *cursor) { char *line = NULL; wchar_t * wtmp = to_wide_string(wk_buf); wtmp[*cursor] = 0; line = wide_string_to_UTF8(wtmp); FREE(wtmp); return line; } static char *getLineAfterCaret(char *wk_buf, unsigned int *cursor, unsigned int *cursor_max) { if (wk_buf) { if (*cursor != *cursor_max) { int len = *cursor_max - *cursor; wchar_t * wtmp = to_wide_string(wk_buf); wchar_t aftercaret[WK_BUF_SIZE]; wcscpy(aftercaret, &wtmp[*cursor]); aftercaret[len + 1] = '\0'; FREE(wtmp); return wide_string_to_UTF8(aftercaret); } } return strdup(""); } static void backspace(int n) { if (n < 1) { return; } while (n--) #ifdef TERMCAP if (BC) { /* if control-H won-t work */ fputs(BC, stdout); } else { /* otherwise just use a normal control-H */ putchar('\010'); } #else putchar('\010'); #endif } static void erase_nchar(int n) { int i; /* fill field with blanks */ for (i = 0; i < n; i++) { putchar(' '); } backspace(n); /* and back up over blanks just written */ } static void TermCompletionOnFiles(char **dictionaryFiles, int sizedictionaryFiles, char *lineBeforeCaret, char *lineAfterCaret, char *filePattern, char *defaultPattern, char **wk_buf, unsigned int *cursor, unsigned int *cursor_max) { if (dictionaryFiles) { if (sizedictionaryFiles == 1) { char *new_line = completeLine(lineBeforeCaret, dictionaryFiles[0], filePattern, defaultPattern, TRUE, lineAfterCaret); if (new_line) { char buflinetmp[WK_BUF_SIZE + 1]; strcpy(buflinetmp, new_line); FREE(new_line); backspace(*cursor); erase_nchar(*cursor_max); *cursor = *cursor_max = 0; CopyLineAtPrompt(wk_buf, buflinetmp, cursor, cursor_max); return; } } else { char *common = getCommonPart(dictionaryFiles, sizedictionaryFiles); displayCompletionDictionary(dictionaryFiles, sizedictionaryFiles, gettext("File or Directory")); printf("\n"); backspace(*cursor); erase_nchar(*cursor_max); *cursor = *cursor_max = 0; printPrompt(WRITE_PROMPT); if (defaultPattern[0] == 0) { int lennewline = (int)strlen(lineBeforeCaret) + (int)strlen(lineAfterCaret); char *new_line = (char *)MALLOC(sizeof(char) * (lennewline + 1)); if (new_line) { strcpy(new_line, lineBeforeCaret); strcat(new_line, lineAfterCaret); CopyLineAtPrompt(wk_buf, new_line, cursor, cursor_max); FREE(new_line); new_line = NULL; } } else if (common) { char *new_line = completeLine(lineBeforeCaret, common, filePattern, defaultPattern, TRUE, lineAfterCaret); if (new_line) { char buflinetmp[WK_BUF_SIZE + 1]; strcpy(buflinetmp, new_line); FREE(new_line); CopyLineAtPrompt(wk_buf, buflinetmp, cursor, cursor_max); } else { int lennewline = (int)strlen(lineBeforeCaret) + (int)strlen(lineAfterCaret); new_line = (char *)MALLOC(sizeof(char) * (lennewline + 1)); if (new_line) { strcpy(new_line, lineBeforeCaret); strcat(new_line, lineAfterCaret); CopyLineAtPrompt(wk_buf, new_line, cursor, cursor_max); FREE(new_line); new_line = NULL; } } } if (common) { FREE(common); common = NULL; } } } } static int CopyLineAtPrompt(char **wk_buf, char *line, unsigned int *cursor, unsigned int *cursor_max) { FREE(*wk_buf); if (line) { wchar_t *wtmp = NULL; //** Copy line to current command buffer, usefull in completion case. *wk_buf = MALLOC(sizeof(char) * strlen(line) + 1); strcpy(*wk_buf, line); backspace(*cursor); /* backspace to beginning of line */ printf("%s", *wk_buf); /* copy to screen */ wtmp = to_wide_string(*wk_buf); *cursor = wcslen(wtmp); /* cursor set at end of line */ FREE(wtmp); /* erase extra characters left over if any */ erase_nchar(GET_MAX(0, (*cursor_max - *cursor))); *cursor_max = *cursor; return 1; } else { *wk_buf = (char*) MALLOC(sizeof(char)); (*wk_buf)[0] = '\0'; } return 0; } static char **concatenateStrings(int *sizearrayofstring, char *string1, char *string2, char *string3, char *string4, char *string5) { int newsize = 0; char **arrayOfString = NULL; *sizearrayofstring = 0; if (string1) { newsize++; } if (string2) { newsize++; } if (string3) { newsize++; } if (string4) { newsize++; } if (string5) { newsize++; } if (newsize > 0) { arrayOfString = (char **)MALLOC(sizeof(char *) * (newsize)); if (arrayOfString) { int i = 0; if (string1) { arrayOfString[i] = string1; i++; } if (string2) { arrayOfString[i] = string2; i++; } if (string3) { arrayOfString[i] = string3; i++; } if (string4) { arrayOfString[i] = string4; i++; } if (string5) { arrayOfString[i] = string5; i++; } *sizearrayofstring = i; } else { *sizearrayofstring = 0; } } return arrayOfString; } static void TermCompletionOnAll(char *lineBeforeCaret, char *lineAfterCaret, char *defaultPattern, char **wk_buf, unsigned int *cursor, unsigned int *cursor_max) { if (defaultPattern) { int numberWordFound = 0; char **completionDictionaryFunctions = NULL; int sizecompletionDictionaryFunctions = 0; char **completionDictionaryCommandWords = NULL; int sizecompletionDictionaryCommandWords = 0; char **completionDictionaryMacros = NULL; int sizecompletionDictionaryMacros = 0; char **completionDictionaryVariables = NULL; int sizecompletionDictionaryVariables = 0; char **completionDictionaryHandleGraphicsProperties = NULL; int sizecompletionDictionaryHandleGraphicsProperties = 0; char **completionDictionaryFields = NULL; int sizecompletionDictionaryFields = 0; completionDictionaryFields = completionOnFields(lineBeforeCaret, defaultPattern, &sizecompletionDictionaryFields); if (!completionDictionaryFields && strcmp(defaultPattern, "")) { completionDictionaryFunctions = completionOnFunctions(defaultPattern, &sizecompletionDictionaryFunctions); completionDictionaryCommandWords = completionOnCommandWords(defaultPattern, &sizecompletionDictionaryCommandWords); completionDictionaryMacros = completionOnMacros(defaultPattern, &sizecompletionDictionaryMacros); completionDictionaryVariables = completionOnVariablesWithoutMacros(defaultPattern, &sizecompletionDictionaryVariables); completionDictionaryHandleGraphicsProperties = completionOnHandleGraphicsProperties(defaultPattern, &sizecompletionDictionaryHandleGraphicsProperties); } numberWordFound = sizecompletionDictionaryFunctions + sizecompletionDictionaryCommandWords + sizecompletionDictionaryMacros + sizecompletionDictionaryVariables + sizecompletionDictionaryHandleGraphicsProperties + sizecompletionDictionaryFields; if (numberWordFound > 0) { if (numberWordFound == 1) { char **completionDictionary = NULL; char *new_line = NULL; if (completionDictionaryFields) { completionDictionary = completionDictionaryFields; } if (completionDictionaryFunctions) { completionDictionary = completionDictionaryFunctions; } if (completionDictionaryCommandWords) { completionDictionary = completionDictionaryCommandWords; } if (completionDictionaryMacros) { completionDictionary = completionDictionaryMacros; } if (completionDictionaryVariables) { completionDictionary = completionDictionaryVariables; } if (completionDictionaryHandleGraphicsProperties) { completionDictionary = completionDictionaryHandleGraphicsProperties; } new_line = completeLine(lineBeforeCaret, completionDictionary[0], NULL, defaultPattern, FALSE, lineAfterCaret); if (new_line) { char buflinetmp[WK_BUF_SIZE + 1]; strcpy(buflinetmp, new_line); FREE(new_line); backspace(*cursor); erase_nchar(*cursor_max); *cursor = *cursor_max = 0; CopyLineAtPrompt(wk_buf, buflinetmp, cursor, cursor_max); } freeArrayOfString(completionDictionary, 1); } else { char *commonAll = NULL; if (completionDictionaryFields) { commonAll = getCommonPart(completionDictionaryFields, sizecompletionDictionaryFields); displayCompletionDictionary(completionDictionaryFields, sizecompletionDictionaryFields, (char *)_("Scilab Fields")); freeArrayOfString(completionDictionaryFields, sizecompletionDictionaryFields); } else { char *commonFunctions = getCommonPart(completionDictionaryFunctions, sizecompletionDictionaryFunctions); char *commonCommandWords = getCommonPart(completionDictionaryCommandWords, sizecompletionDictionaryCommandWords); char *commonMacros = getCommonPart(completionDictionaryMacros, sizecompletionDictionaryMacros); char *commonVariables = getCommonPart(completionDictionaryVariables, sizecompletionDictionaryVariables); char *commonHandleGraphicsProperties = getCommonPart(completionDictionaryHandleGraphicsProperties, sizecompletionDictionaryHandleGraphicsProperties); int sizecommonsDictionary = 0; char **commonsDictionary = concatenateStrings(&sizecommonsDictionary, commonFunctions, commonMacros, commonCommandWords, commonVariables, commonHandleGraphicsProperties); if (sizecommonsDictionary > 0) { if (sizecommonsDictionary == 1) { commonAll = strdup(commonsDictionary[0]); } else { commonAll = getCommonPart(commonsDictionary, sizecommonsDictionary); } freeArrayOfString(commonsDictionary, sizecommonsDictionary); } displayCompletionDictionary(completionDictionaryFunctions, sizecompletionDictionaryFunctions, (char *)_("Scilab Function")); displayCompletionDictionary(completionDictionaryCommandWords, sizecompletionDictionaryCommandWords, (char *)_("Scilab Command")); displayCompletionDictionary(completionDictionaryMacros, sizecompletionDictionaryMacros, (char *)_("Scilab Macro")); displayCompletionDictionary(completionDictionaryVariables, sizecompletionDictionaryVariables, (char *)_("Scilab Variable")); displayCompletionDictionary(completionDictionaryHandleGraphicsProperties, sizecompletionDictionaryHandleGraphicsProperties, (char *)_("Graphics handle field")); freeArrayOfString(completionDictionaryFunctions, sizecompletionDictionaryFunctions); freeArrayOfString(completionDictionaryCommandWords, sizecompletionDictionaryCommandWords); freeArrayOfString(completionDictionaryMacros, sizecompletionDictionaryMacros); freeArrayOfString(completionDictionaryVariables, sizecompletionDictionaryVariables); freeArrayOfString(completionDictionaryHandleGraphicsProperties, sizecompletionDictionaryHandleGraphicsProperties); } printf("\n"); backspace(*cursor); erase_nchar(*cursor_max); *cursor = *cursor_max = 0; printPrompt(WRITE_PROMPT); if (commonAll) { char *new_line = NULL; new_line = completeLine(lineBeforeCaret, commonAll, NULL, defaultPattern, FALSE, lineAfterCaret); if (new_line) { char buflinetmp[WK_BUF_SIZE + 1]; strcpy(buflinetmp, new_line); FREE(new_line); CopyLineAtPrompt(wk_buf, buflinetmp, cursor, cursor_max); } FREE(commonAll); commonAll = NULL; } } } } } static void displayCompletionDictionary(char **dictionary, int sizedictionary, char *namedictionary) { #define MAX_LINE_SIZE 79 /* 80 - 1 the leading space */ if (dictionary) { int i = 0; int lenCurrentLine = 0; /* Set the category */ setCharDisplay(DISP_ITALIC); printf("\n"); printf("%s", namedictionary); printf("%s", ":"); printf("\n"); /* Reset to set back the default display. */ setCharDisplay(DISP_LAST_SET); /* Set the list of completion */ setCharDisplay(DISP_RESET); for (i = 0; i < sizedictionary; i++) { int newlenLine = lenCurrentLine + (int)strlen(dictionary[i]) + (int)strlen(" "); if ((lenCurrentLine + newlenLine) > MAX_LINE_SIZE) { printf("\n"); lenCurrentLine = 0; } else { lenCurrentLine = newlenLine; } printf("%s", dictionary[i]); printf("%s", " "); } printf("\n"); /* Reset to set back the default display. */ setCharDisplay(DISP_LAST_SET); } }