@@ -354,16 +354,55 @@ void ConsoleDialog::createOutputWindow(HWND hParentWindow)
354354{
355355 m_scintilla = (HWND)::SendMessage (_hParent, NPPM_CREATESCINTILLAHANDLE, 0 , reinterpret_cast <LPARAM>(hParentWindow));
356356 callScintilla (SCI_SETREADONLY, 1 , 0 );
357+
358+ /* Style bits
359+ * LSB 0 - stderr = 1
360+ * 1 - hotspot
361+ * 2 - warning
362+ * ... to be continued
363+ */
364+
365+
366+ // 0 is stdout, black text
357367 callScintilla (SCI_STYLESETSIZE, 0 /* = style number */ , 8 /* = size in points */ );
368+
369+ // 1 is stderr, red text
358370 callScintilla (SCI_STYLESETSIZE, 1 /* = style number */ , 8 /* = size in points */ );
359371 callScintilla (SCI_STYLESETFORE, 1 , RGB (250 , 0 , 0 ));
372+
373+ // 2 is stdout, black text, underline hotspot
360374 callScintilla (SCI_STYLESETSIZE, 2 /* = style number */ , 8 /* = size in points */ );
361375 callScintilla (SCI_STYLESETUNDERLINE, 2 /* = style number */ , 1 /* = underline */ );
376+ callScintilla (SCI_STYLESETHOTSPOT, 2 , 1 );
377+
378+ // 3 is stderr, red text, underline hotspot
362379 callScintilla (SCI_STYLESETSIZE, 3 /* = style number */ , 8 /* = size in points */ );
363380 callScintilla (SCI_STYLESETFORE, 3 , RGB (250 , 0 , 0 ));
364381 callScintilla (SCI_STYLESETUNDERLINE, 3 /* = style number */ , 1 /* = underline */ );
365- callScintilla (SCI_STYLESETHOTSPOT, 2 , 1 );
366382 callScintilla (SCI_STYLESETHOTSPOT, 3 , 1 );
383+
384+ // 4 stdout warning without hotspot
385+ callScintilla (SCI_STYLESETSIZE, 4 /* = style number */ , 8 /* = size in points */ );
386+ callScintilla (SCI_STYLESETFORE, 4 , RGB (199 , 175 , 7 )); // mucky yellow
387+
388+
389+ // 5 stderr warning without hotspot
390+ callScintilla (SCI_STYLESETSIZE, 5 /* = style number */ , 8 /* = size in points */ );
391+ callScintilla (SCI_STYLESETFORE, 5 , RGB (255 , 128 , 64 )); // orange
392+
393+
394+ // 6 is hotspot, stdout, warning
395+ callScintilla (SCI_STYLESETSIZE, 6 /* = style number */ , 8 /* = size in points */ );
396+ callScintilla (SCI_STYLESETFORE, 6 , RGB (199 , 175 , 7 )); // mucky yellow
397+ callScintilla (SCI_STYLESETUNDERLINE, 6 /* = style number */ , 1 /* = underline */ );
398+ callScintilla (SCI_STYLESETHOTSPOT, 6 , 1 );
399+
400+ // 7 is hotspot, stderr, warning
401+ callScintilla (SCI_STYLESETSIZE, 7 /* = style number */ , 8 /* = size in points */ );
402+ callScintilla (SCI_STYLESETFORE, 7 , RGB (255 , 128 , 64 )); // orange
403+ callScintilla (SCI_STYLESETUNDERLINE, 7 /* = style number */ , 1 /* = underline */ );
404+ callScintilla (SCI_STYLESETHOTSPOT, 7 , 1 );
405+
367406 callScintilla (SCI_USEPOPUP, 0 );
368407 callScintilla (SCI_SETLEXER, SCLEX_CONTAINER);
369408}
@@ -484,7 +523,7 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification)
484523 lineDetails.line = new char [lineDetails.lineLength + 1 ];
485524 callScintilla (SCI_GETLINE, lineNumber, reinterpret_cast <LPARAM>(lineDetails.line ));
486525 lineDetails.line [lineDetails.lineLength ] = ' \0 ' ;
487-
526+ lineDetails. errorLevel = EL_UNSET;
488527
489528
490529 if (parseLine (&lineDetails))
@@ -494,10 +533,44 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification)
494533 // Check that it's not just a file called '<console>'
495534 if (strncmp (lineDetails.line + lineDetails.filenameStart , " <console>" , lineDetails.filenameEnd - lineDetails.filenameStart ))
496535 {
497- callScintilla (SCI_STARTSTYLING, startPos + lineDetails.filenameStart , 0x02 );
498- callScintilla (SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart , 0x02 );
499- callScintilla (SCI_STARTSTYLING, startPos + lineDetails.filenameEnd , 0x02 );
500- callScintilla (SCI_SETSTYLING, lineDetails.lineLength - lineDetails.filenameEnd , 0x00 );
536+ int mask, style;
537+ switch (lineDetails.errorLevel )
538+ {
539+ case EL_WARNING:
540+ mask = 0x04 ;
541+ style = 0x04 ;
542+ break ;
543+
544+ case EL_ERROR:
545+ mask = 0x01 ;
546+ style = 0x01 ;
547+ break ;
548+
549+ case EL_UNSET:
550+ case EL_INFO:
551+ default :
552+ mask = 0x00 ;
553+ style = 0x00 ;
554+ break ;
555+ }
556+
557+ if (lineDetails.filenameStart > 0 )
558+ {
559+ callScintilla (SCI_STARTSTYLING, startPos, mask);
560+ callScintilla (SCI_SETSTYLING, lineDetails.filenameStart , style);
561+ }
562+
563+
564+ callScintilla (SCI_STARTSTYLING, startPos + lineDetails.filenameStart , mask | 0x02 );
565+ callScintilla (SCI_SETSTYLING, lineDetails.filenameEnd - lineDetails.filenameStart , style | 0x02 );
566+
567+ if (lineDetails.lineLength > lineDetails.filenameEnd )
568+ {
569+ callScintilla (SCI_STARTSTYLING, startPos + lineDetails.filenameEnd , mask);
570+ callScintilla (SCI_SETSTYLING, lineDetails.lineLength - lineDetails.filenameEnd , style);
571+ }
572+
573+
501574 }
502575 }
503576
@@ -513,39 +586,63 @@ void ConsoleDialog::onStyleNeeded(SCNotification* notification)
513586
514587bool ConsoleDialog::parseLine (LineDetails *lineDetails)
515588{
516- if (0 == strncmp (lineDetails->line , " File \" " , 8 ))
589+ // Eg.
590+ // File "C:\Users\Dave\AppData\Roaming\Notepad++\plugins\Config\PythonScript\scripts\fourth.py", line 2, in <module>
591+ if (0 == strncmp (lineDetails->line , " File \" " , 8 )
592+ && parsePythonErrorLine (lineDetails))
517593 {
518- return parsePythonErrorLine (lineDetails) ;
594+ return true ;
519595 }
520-
521- if (0 == strncmp (lineDetails->line + 1 , " :\\ " , 2 ))
596+
597+ // Eg.
598+ // e:\work\pythonscript\pythonscript\src\consoledialog.cpp(523): error C2065: 'ee' : undeclared identifier
599+ // Potentially with spaces in front if MSBUILD used
600+ // Line number can contain "," for column (523,5)
601+ if (parseVSErrorLine (lineDetails))
522602 {
523- return parseVSErrorLine (lineDetails) ;
603+ return true ;
524604 }
525605
606+ // Eg.
607+ // C:/PalmDev/sdk-4/include/Core/System/NetMgr.h:550: warning: ignoring pragma: ;
608+ if (parseGCCErrorLine (lineDetails))
609+ {
610+ return true ;
611+ }
612+
526613 return false ;
527614}
528615
529616bool ConsoleDialog::parseVSErrorLine (LineDetails *lineDetails)
530617{
531618 enum StyleState
532619 {
620+ SS_BEGIN,
533621 SS_FILENAME,
534622 SS_LINENUMBER,
623+ SS_ERRORTYPE,
535624 SS_EXIT
536625 } styleState;
537626
538627 bool retVal = false ;
539- styleState = SS_FILENAME ;
628+ styleState = SS_BEGIN ;
540629
541630 int pos = 0 ;
542- lineDetails->filenameStart = 0 ;
543631 lineDetails->errorLineNo = -1 ;
544632
545633 while (styleState != SS_EXIT)
546634 {
547635 switch (styleState)
548636 {
637+ case SS_BEGIN:
638+ while (lineDetails->line [pos] == ' ' )
639+ {
640+ ++pos;
641+ }
642+ lineDetails->filenameStart = pos;
643+ styleState = SS_FILENAME;
644+ break ;
645+
549646 case SS_FILENAME:
550647 while (lineDetails->line [pos] != ' (' && pos < lineDetails->lineLength )
551648 {
@@ -566,18 +663,137 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails)
566663 case SS_LINENUMBER:
567664 {
568665 int startLineNoPos = pos;
666+ int endLineNoPos;
569667 while (lineDetails->line [pos] >= ' 0' && lineDetails->line [pos] <= ' 9' && pos < lineDetails->lineLength )
570668 {
571669 ++pos;
572670 }
671+ endLineNoPos = pos;
672+
673+ if (pos < (lineDetails->lineLength + 1 )
674+ && lineDetails->line [pos] == ' ,' )
675+ {
676+ ++pos;
677+ while (lineDetails->line [pos] >= ' 0' && lineDetails->line [pos] <= ' 9' && pos < lineDetails->lineLength )
678+ {
679+ ++pos;
680+ }
681+ }
682+
683+
573684 if (pos < (lineDetails->lineLength + 1 )
574685 && lineDetails->line [pos] == ' )'
575686 && lineDetails->line [pos+1 ] == ' :' )
687+ {
688+ char *lineNumber = new char [endLineNoPos - startLineNoPos + 2 ];
689+ strncpy_s (lineNumber, endLineNoPos - startLineNoPos + 2 , lineDetails->line + startLineNoPos, endLineNoPos - startLineNoPos);
690+ lineDetails->errorLineNo = atoi (lineNumber) - 1 ;
691+ delete[] lineNumber;
692+ lineDetails->filenameEnd = startLineNoPos - 1 ;
693+ retVal = true ;
694+ pos += 3 ; // jump past "): " to either error or warning
695+ styleState = SS_ERRORTYPE;
696+ }
697+ else
698+ {
699+ pos = startLineNoPos + 1 ;
700+ styleState = SS_FILENAME;
701+ }
702+ break ;
703+ }
704+
705+ case SS_ERRORTYPE:
706+ if (0 == strncmp (lineDetails->line + pos, " error" , 5 ))
707+ {
708+ lineDetails->errorLevel = EL_ERROR;
709+ }
710+ else if (0 == strncmp (lineDetails->line + pos, " warning" , 7 ))
711+ {
712+ lineDetails->errorLevel = EL_WARNING;
713+ }
714+ styleState = SS_EXIT;
715+ break ;
716+
717+ case SS_EXIT:
718+ break ;
719+
720+ default :
721+ styleState = SS_EXIT;
722+ break ;
723+ }
724+ }
725+ return retVal;
726+ }
727+
728+
729+ bool ConsoleDialog::parseGCCErrorLine (LineDetails *lineDetails)
730+ {
731+ enum StyleState
732+ {
733+ SS_FILENAME,
734+ SS_LINENUMBER,
735+ SS_ERRORTYPE,
736+ SS_EXIT
737+ } styleState;
738+
739+ bool retVal = false ;
740+ styleState = SS_FILENAME;
741+
742+ int pos = 0 ;
743+ lineDetails->filenameStart = 0 ;
744+ lineDetails->errorLineNo = -1 ;
745+
746+ while (styleState != SS_EXIT)
747+ {
748+ switch (styleState)
749+ {
750+ case SS_FILENAME:
751+ {
752+ bool isEscaped = false ;
753+ while ((lineDetails->line [pos] != ' :' || pos == 1 ) && pos < lineDetails->lineLength )
754+ {
755+ // Unescaped space, so leave - this isn't a gcc error
756+ if (lineDetails->line [pos] == ' ' && !isEscaped)
757+ {
758+ styleState = SS_EXIT;
759+ break ;
760+ }
761+
762+ if (lineDetails->line [pos] == ' \\ ' )
763+ isEscaped = true ;
764+
765+ ++pos;
766+
767+ isEscaped = false ;
768+ }
769+
770+ if (lineDetails->line [pos] == ' :' ) // Found the colon for line no
771+ {
772+ ++pos;
773+ styleState = SS_LINENUMBER;
774+ }
775+ else
776+ {
777+ styleState = SS_EXIT;
778+ }
779+ }
780+ break ;
781+
782+ case SS_LINENUMBER:
783+ {
784+ int startLineNoPos = pos;
785+ while (lineDetails->line [pos] >= ' 0' && lineDetails->line [pos] <= ' 9' && pos < lineDetails->lineLength )
786+ {
787+ ++pos;
788+ }
789+ if (pos < (lineDetails->lineLength + 1 )
790+ && lineDetails->line [pos] == ' :' )
576791 {
577792 lineDetails->errorLineNo = atoi (lineDetails->line + startLineNoPos) - 1 ;
578793 lineDetails->filenameEnd = startLineNoPos - 1 ;
579794 retVal = true ;
580- styleState = SS_EXIT;
795+ pos += 2 ;
796+ styleState = SS_ERRORTYPE;
581797 }
582798 else
583799 {
@@ -586,6 +802,17 @@ bool ConsoleDialog::parseVSErrorLine(LineDetails *lineDetails)
586802 }
587803 break ;
588804 }
805+ case SS_ERRORTYPE:
806+ if (0 == strncmp (lineDetails->line + pos, " error" , 5 ))
807+ {
808+ lineDetails->errorLevel = EL_ERROR;
809+ }
810+ else if (0 == strncmp (lineDetails->line + pos, " warning" , 7 ))
811+ {
812+ lineDetails->errorLevel = EL_WARNING;
813+ }
814+ styleState = SS_EXIT;
815+ break ;
589816
590817 case SS_EXIT:
591818 break ;
@@ -677,17 +904,7 @@ bool ConsoleDialog::parsePythonErrorLine(LineDetails *lineDetails)
677904
678905
679906
680- void ConsoleDialog::styleDefaultLine (int lineNumber, int lineLength, const char * /* line */ )
681- {
682-
683- int linePosition = callScintilla (SCI_POSITIONFROMLINE, lineNumber);
684- // Set the mask to the hotspot bit (0x02)
685-
686- callScintilla (SCI_STARTSTYLING, linePosition, 0x02 );
687- // and declare no hotspots
688- callScintilla (SCI_SETSTYLING, lineLength, 0 );
689907
690- }
691908
692909
693910void ConsoleDialog::onHotspotClick (SCNotification* notification)
0 commit comments