diff options
author | Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> | 2008-03-11 21:46:58 -0300 |
---|---|---|
committer | Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> | 2008-07-02 19:04:52 -0300 |
commit | a2c47d3487aaf4667926195ba3f5b05b94626daf (patch) | |
tree | b41f7989704e17c4687e4e7b3ba43a61864a38ba /util.c | |
parent | a1949714b99a502a57b3dd7a99e619c10211d9fc (diff) |
Fix several generic bugs including:
o Several memory read/write errors.
o Implement smarter XeditPrintf that will show how many times a text
has been printed.
o Check all arguments to XeditPrintf to ensure the '%' character cannot
be sent to it.
o Some minor reindentation to code that still had the original 2 spaces
indentation.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 128 |
1 files changed, 94 insertions, 34 deletions
@@ -28,7 +28,10 @@ #include <stdio.h> #include <stdarg.h> + +#include <libgen.h> /* POSIX basename() */ #include <stdlib.h> /* for realpath() */ +#include <errno.h> /* for ENOENT */ #include "xedit.h" #include <X11/Xfuncs.h> @@ -72,41 +75,63 @@ extern XawTextWrapMode wrapmodes[3]; void XeditPrintf(const char *format, ...) { - char *str; - size_t size; - va_list va, - va2; - XawTextBlock text; - XawTextPosition pos; - - va_start(va, format); + static struct { + XawTextPosition last; + int size; + int length; + int repeat; + char *buffer; + } info; + + size_t size; + va_list va; + XawTextBlock text; + XawTextPosition left, right; + char buffer[BUFSIZ]; + char *string, rbuffer[32]; - va_copy(va2, va); - size = vsnprintf(NULL, 0, format, va2); - va_end(va2); - - str = (char *)malloc(size + 1); - if (str == NULL) - return; - - vsnprintf(str, size + 1, format, va); - str[size] = 0; - + va_start(va, format); + size = vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); - - pos = XawTextSourceScan(XawTextGetSource(messwidget), - 0, XawstAll, XawsdRight, 1, True); - text.length = strlen(str); - text.ptr = str; - text.firstPos = 0; - text.format = FMT8BIT; + /* Should never happen... */ + if (size >= sizeof(buffer)) { + strcpy(buffer + sizeof(buffer) - 5, "...\n"); + size = sizeof(buffer) - 1; + } + else if (size) { + left = right = XawTextSourceScan(XawTextGetSource(messwidget), + 0, XawstAll, XawsdRight, 1, True); + + if (left == info.last && + info.buffer && + strcmp(buffer, info.buffer) == 0) { + string = rbuffer; + if (info.repeat == 1) + left -= info.buffer[strlen(info.buffer) - 1] == '\n'; + else + left -= info.length; + size = info.length = XmuSnprintf(rbuffer, sizeof(rbuffer), + " [%d times]\n", ++info.repeat); + } + else { + string = buffer; + if (size >= info.size) + info.buffer = XtMalloc(size + 1); + strcpy(info.buffer, buffer); + info.repeat = 1; + } + + text.length = size; + text.ptr = string; + text.firstPos = 0; + text.format = FMT8BIT; - XawTextReplace(messwidget, pos, pos, &text); + XawTextReplace(messwidget, left, right, &text); - XawTextSetInsertionPoint(messwidget, pos + text.length); - - free(str); + info.last = left + text.length; + XawTextSetInsertionPoint(messwidget, info.last); + } } Widget @@ -243,7 +268,7 @@ AddTextSource(Widget source, char *name, char *filename, int flags, else ++wid_name; item->sme = XtVaCreateManagedWidget(wid_name, smeBSBObjectClass, - flist.popup, XtNlabel, filename, + flist.popup, XtNlabel, item->filename, NULL, NULL); XtAddCallback(item->sme, XtNcallback, SwitchSourceCallback, (XtPointer)item); @@ -454,18 +479,53 @@ SwitchTextSource(xedit_flist_item *item) XtSetArg(args[num_args], XtNstring, NULL); ++num_args; } XtSetValues(filenamewindow, args, num_args); + /* XXX This probably should be done by the TextWidget, i.e. notice + * if the cursor became inivisible due to an horizontal scroll */ + _XawTextShowPosition((TextWidget)filenamewindow); } -/* XXX sizeof(name) must match argument size for realpath */ -static char name[BUFSIZ]; char * ResolveName(char *filename) { +#ifndef __UNIXOS2__ + static char *name; + char *result, *tmp = name; +#endif + if (filename == NULL) filename = GetString(filenamewindow); #ifndef __UNIXOS2__ - return (realpath(filename, name)); + /* Ensure not passing the same pointer again to realpath */ + name = XtMalloc(BUFSIZ); + XtFree(tmp); + result = realpath(filename, name); + + if (result == NULL && errno == ENOENT) { + int length; + char *dir, *file; + + length = strlen(filename); + tmp = dir = XtMalloc(length + 1); + strcpy(dir, filename); + + file = basename(filename); + dir = dirname(tmp); + + /* Creating a new file? */ + if (dir && file && strcmp(dir, file) && + access(dir, F_OK) == 0 && + (result = realpath(dir, name)) == name) { + int length = strlen(result); + + XmuSnprintf(result + length, BUFSIZ - length, "%s%s", + dir[length - 1] == '/' ? "" : "/", file); + } + + XtFree(tmp); + } + + return (result); #else return filename; #endif |