【问题标题】:Parse string for coloring text in Xlib解析字符串以在 Xlib 中为文本着色
【发布时间】:2014-07-23 11:08:17
【问题描述】:

我正在尝试为 DWM 6.1 编写一个补丁来为状态栏着色,到目前为止我已经设法做到了,但我使用像 \x01 这样的十六进制字符来表示颜色。这样做我发现了一个问题。当 dwm 获取状态栏的宽度时,也与转义字符一起计数,导致状态栏错位。

我编写了一个虚拟程序来尝试解决这个问题。我的想法是,给定以下状态文本:

char buf[] = "Hello World\x01, Bye!\x02";

那必须用颜色1写Hello World,用颜色2写, Bye!。我想解析文本得到:

char cleanBuf[] = "Hello World, Bye!";

我已经这样做了。但是现在我需要以某种方式记住转义序列的位置,以便用相应的颜色绘制文本。我认为有一个stack 按颜色出现的顺序存储颜色,在这种情况下,堆栈将有{color1, color2}。还有一个结构,其文本的开始和结束指针必须是一种颜色,对于Hello World,我需要一个指向H 的指针和另一个指向d 的指针。这样我就可以创建一个新字符串来解析为XDrawString 并用相应的颜色打印出来。

这是最好的方法吗?我想我把事情复杂化了一点。如果你想尝试,完整的程序是here。我在这里粘贴主循环:

while (1) {
  XNextEvent(dpy, &e);

  if (e.type == Expose && e.xexpose.count < 1) {

    char buf[] = "Hello World\x01, Bye!\x02";
    char cleanBuf[strlen(buf)];
    memset(cleanBuf, 0, strlen(cleanBuf));
    char *copy = strdup(buf);
    char *delim = "\x01\x02";
    char *res = strtok(buf, delim);
    strcat(cleanBuf, res);
    unsigned long color1 = 0xff0000;
    unsigned long color2 = 0x00ff00;
    unsigned long color;
    int x = 10;
    while (res) {
      /* Figure out what delimiter was used */
      // Thanks to http://stackoverflow.com/a/12460511/1612432
      char deli = copy[res - buf + strlen(res)];
      if (deli == '\x01')
        color = color1;
      else if (deli == '\x02')
        color = color2;
      else
        color = 0xffffff;
      XSetForeground(dpy, gc, color);
      XDrawString(dpy, win, gc, x, 10, res, strlen(res));
      x += 50;
      res = strtok(0, delim);
      if (res)
        strcat(cleanBuf, res);
    }
    free(copy);

  } else if (e.type == ButtonPress)
    break;

}

【问题讨论】:

  • 还不错。可能的优化:XDrawString 需要一个指向字符串的指针,但也需要它的 length。这意味着你可以不用strlen 调用——你所需要的只是字符串开始,以及每个部分都有一个颜色+长度对的数组。因此,您不必物理地创建字符串的每个部分的副本。
  • 谢谢,我会努力的,现在我正在努力完成这项工作。如果我得到它的工作,我会发布解决方案。

标签: c parsing xlib x-dwm


【解决方案1】:

我终于可以用下面的方法解析字符串了:

void
parsestatus(char *text, unsigned long *color_queue, char tokens[][256]) {

  // TODO move variables that can to main in order to not recreated them
  char *copy = strdup(text);
  char cleanBuf[strlen(text)];
  memset(cleanBuf, 0, strlen(cleanBuf));

  char delim[NUMCOLORS+1];

  /* Thanks to http://stackoverflow.com/a/24931903/1612432 */
  for (int i = 0; i < NUMCOLORS; ++i)
      delim[i] = i + 1;
  /* Terminates as string */
  delim[NUMCOLORS] = '\0';

  char *res = strtok(copy, delim);
  strcat(tokens[0], res);
  strcat(cleanBuf, res);
  int i = 1;

  while (res) {
    /* Figure out what delimiter was used */
    // Thanks to http://stackoverflow.com/a/12460511/1612432
    int deli = text[res - copy + strlen(res)] - 1;
    color_queue[i-1] = colors[deli];
    res = strtok(0, delim);
    if (res){
      strcat(tokens[i++], res);
      strcat(cleanBuf, res);
    }
  }
  free(copy);
  strncpy(text, cleanBuf, strlen(cleanBuf));
  text[strlen(cleanBuf)] = '\0';
}

然后,在每次调用 XmbDrawString 之后,我都会减去终止字符的长度,如下所示:

tx += TEXTW(text[k]) - TEXTW("\x0");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多